#ifndef DYN_CONTROLCHAOS_H
#define DYN_CONTROLCHAOS_H

#include <armadillo>

#include "../utilities/dyn_multifunctor_multiMaps.h"

#define CALL_MEMBER_FN(object, ptrToMember) ((object)->*(ptrToMember))

typedef double (MultiMaps::*mapsGetPtr)();
typedef void (MultiMaps::*mapsSetPtr)(double para);

/*! \author Joey Dumont <joey.dumont@gmail.com>
 *
 * \date 2012-08-24
 *
 * \brief Abstract that defines common methods
 * for controlling chaos.
 *
 * The control() function is the same for almost every
 * control algorithm. We modify the parameter at
 * every iteration by a value determined the
 * the computeDelta(int, rowvec) method.
 *
 * We use member function pointers to access
 * the parameter we want to control.
 *
 * This abstact class defines
 * the basic structure of an algorithm
 * for controlling chaos. It provides
 * a skeleton for the implementation of
 * several control methods as well
 * as general-purpose implementation
 * of the method.
 *
 * \copyright LGPL
 */

class ControlChaos
{
public:
    /*! Base constructor will be the base
     * of all control routines.
     */
    ControlChaos(MultiMaps* _map,
                 mat orbitPoints,
                 colvec initCond,
                 mapsGetPtr getPtr,
                 mapsSetPtr setPtr,
                 double deltaMax,
                 double epsilonNeighborhood,
                 int controlIterations,
                 int maxIterations);

    /*! @name Accessor functions.
     * We define virtual accessor
     * functions that will be used by the
     * derived classes.
     */
    //@{
    virtual MultiMaps* getMultiMap(){return map;}
    virtual mat getOrbitPoints(){return orbitPoints;}
    virtual colvec getInitialCondition(){return init;}
    virtual colvec getDelta(){return delta;}
    virtual double getDefaultParameter(){return defaultParameter;}
    virtual double getDeltaMax(){return deltaMax;}
    virtual double getEpsilonNeighborhood(){return epsilonNeighborhood;}
    virtual int getIteratesToControl(){return iteratesToControl;}
    virtual int getControlIterations(){return controlIterations;}
    virtual int getMaxIterations(){return maxIterations;}

    virtual void setMultiMap(MultiMaps* myMap){map = myMap;}
    virtual void setOrbitPoints(mat myOrbits){orbitPoints = myOrbits;}
    virtual void setInitialCondition(colvec initCond){init = initCond;}
    virtual void setDefaultParameter(double myPara){defaultParameter = myPara;}
    virtual void setDeltaMax(double myDeltaMax){deltaMax = myDeltaMax;}
    virtual void setEpsilonNeighborhood(double myEpsilon){epsilonNeighborhood = myEpsilon;}
    virtual void setIteratesToControl(int numberOfIterationsToControl){iteratesToControl = numberOfIterationsToControl;}
    virtual void setControlIterations(int myIterations){controlIterations = myIterations;}
    virtual void setMaxIterations(int myMaxIterations){maxIterations = myMaxIterations;}
    //@}

    /*! @name Controlling Chaos algorithm
     * The main function control() shall be comprised
     * of pure virtual functions that will have to be
     * re-implemented in the derived classes. The derived
     * classes define the control criterion and
     * any other information they need to actually
     * perform the control.
     */
    //@{
    virtual mat control();
    virtual double computeDelta(int,rowvec)=0;
    //@}

protected:
    /*! @name General parameters
     * We define the general parameters
     * and variables we need to access
     * or store while controlling chaos.
     */
    //@{
    MultiMaps* map;
    mat orbitPoints;
    colvec init;
    colvec delta;
    mapsGetPtr getParameter;
    mapsSetPtr setParameter;
    double defaultParameter;
    double deltaMax;
    double epsilonNeighborhood;
    int iteratesToControl;
    int controlIterations;
    int maxIterations;
    //@}

};

#endif // DYN_CONTROLCHAOS_H
